home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
106_01
/
stdlib2.c
< prev
next >
Wrap
Text File
|
1980-07-08
|
20KB
|
831 lines
/* ---------------------------------------------------------
Mods by H Moran:
In case you wish to adopt some but not all of the mods:
Lines modified by HRM marked with comment 'HRM mod'
Lines added by HRM marked with comment 'HRM'
1) added functions: for list reader and punch devices
lprintf pprintf -- list and punch devices
rscanf -- reader device
rgets -- reader device
lputs pputs -- list and punch devices
lputc pputc -- list and punch devices
rgetc -- reader device
2) sprintf() modified to use '0' for left fill char
when radix is not decimal.
3) binary field spec added to sprintf() and sscanf()
spec used is %b
4) pad char for non-decimal numeric fields in sprintf()
changed to '0'
5) printing of a..f changed to A..F in _uspr()
6) fgets() fixed to remember reception of 0x1a
and handle it as EOF. See the one caveat in
the modified comments.
-------------------------------------------------------
*/
/*
This file contains the source for the following
library functions:
printf ** fprintf ** sprintf *
scanf fscanf sscanf
gets fgets
puts fputs
swapin ***
*) rewritten for 1.31
**) work differently since they use the new "sprintf"
***) brand new for 1.31
An alternate version of "sprintf" is given in the file
FLOAT.C for use with floating point numbers; see FLOAT.C
for details. Note that "sprintf" is used by "printf", so
this really amounts to an alternate version of "printf",
too.
Note that all the upper-level formatted I/O functions
("printf", "fprintf", "scanf", and "fscanf") now use
"sprintf" and "sscanf" for doing conversions. While
this leads to very structured source code, it also
means that calls to "scanf" and "fscanf" must process
ALL the information on a line of text; if the format
string runs out and there is still text left in the
line being processed, the text will be lost (i.e., the
NEXT scanf or fscanf call will NOT find it.)
Also note that temporary work space is declared within
each of the high-level functions as a one-dimensional
character array. The length limit on this array is
presently set to 132 by the #define MAXLINE statement;
if you intend to create longer lines through printf,
fprintf, scanf, or fscanf calls, be SURE to raise this
limit by changing the #define statement.
Some misc. comments on hacking text files with CP/M:
The conventional CP/M text format calls for each
line to be terminated by a CR-LF combination. In the
world of C programming, though, we like to just use
a single LF (also called a newline) to terminate
lines. AND SO, the functions which deal with reading
and writing text from disk files to memory and vice-
versa ("fgets", "fputs") take special pains to convert
CR-LF combinations into single '\n' characters when
reading from disk ("fgets"), and convert '\n' char-
acters to CR-LF combinations when writing TO disk
("fputs"). This allows the C programmer to do things
in style, dealing only with a single line terminator,
while maintaining compatibility with the CP/M text
format (so that, for example, a text file can be
"type"d under the CCP.)
To confuse matters further, the "gets" function
(which simply buffers up a line of console input)
terminates a line with '\0' (a zero byte) instead
of CR or LF. Thus, if you wanted to read in lines
of input from the console and write them to a file,
you'd have to manually put out the CR and LF at the
end of every line. Oh, and don't forget the 0x1a
(control-Z) at the end of the file! Hey, kiddies,
isn't CP/M fun to work with???
Also, watch out when reading in text files using
"getc". While a text file is USUALLY terminated
with a control-Z, it MAY NOT BE if the file ends
on an even sector boundary. This means that there
are two possible return values from "getc" which
signal and EOF: 0x1a (control-Z), and -1 (or 255
if you assign it to a char variable.)
*/
#define RAM 0 /* start of CP/M RAM area */
#define MAXLINE 132 /* maximum length of text line */
#define EOF -1 /* End of file val returned by getc */
#define NULL 0 /* Returned by fgets on EOF */
char toupper(), isdigit();
struct buf {
int fd;
int nleft;
char *nextp;
char buff[128];
};
/*
printf
usage:
printf(format, arg1, arg2, ...);
Note that since the sprintf function is used to
form the output string and then puts is used to
actually print it out, care must be taken to
avoid generating null (zero) bytes in the output,
since such a byte will terminate printing of the
string by puts. Thus, a statment such as:
printf("%c foo",'\0');
would print nothing at all.
See the "sprintf" documentation, below, for more info.
*/
printf(format)
char *format;
{
char line[MAXLINE];
_mvl();
sprintf(line,format);
puts(line);
}
/*
fprintf:
Like printf, except that the first argument is
a pointer to a buffered I/O buffer, and the text
is written to the file described by the buffer:
(-1 returned on error)
usage:
fprintf(iobuf, format, arg1, arg2, ...);
*/
fprintf(iobuf,format)
char *format;
struct buf *iobuf;
{
char text[MAXLINE];
sprintf(text);
return fputs(text,iobuf);
}
/*
fscanf:
Like scanf, except that the first argument is
a pointer to a buffered input file buffer, and
the text is taken from the file instead of from
the console.
Usage:
fscanf(iobuf, format, ptr1, ptr2, ...);
Returns number of items matched (zero on EOF.)
Note that any unprocessed text is lost forever. Each
time scanf is called, a new line of input is gotten
from the file, and any information left over from
the last call is wiped out. Thus, the text in the
file must be arranged such that a single call to
fscanf will always get all the required data on a
line.
*/
int fscanf(iobuf,format,arg1)
char *format;
struct buf *iobuf;
{
char text[MAXLINE];
if (!fgets(text,iobuf)) return 0;
return sscanf(text,format,arg1);
}
/*
scanf:
This one accepts a line of input text from the
console, and converts the text to the required
binary or alphanumeric form (see Kernighan &
Ritchie for a more thorough description):
Usage:
scanf(format, ptr1, ptr2, ...);
Returns number of items matched.
Since a new line of text must be entered from the
console each time scanf is called, any unprocessed
text left over from the last call is lost forever.
This is a difference between BDS scanf and UNIX
scanf. Another is that the field width specification
is not supported here.
*/
scanf(format)
char *format;
{
char line[MAXLINE];
_mvl();
gets(line);
sscanf(line,format);
}
/*
Internal function to move all function arguments
over one place to the right, to make room for
a new argument in the first position. This is
necessary so that, for example, "sprintf" can
be called from within "printf" without clobbering
one of the arguments. This is NOT a portable
feature of BDS C, and in fact represents one of
the biggest kludges in the package. Oh well; live
and learn.
*/
_mvl()
{
int count, *ptr;
ptr = (RAM + 0x3f7 + 0x2e);
count = 23;
while (count--) *ptr = *--ptr;
}
/*
sprintf:
Like fprintf, except a string pointer is specified
instead of a buffer pointer. The text is written
to where the string pointer points.
Usage:
sprintf(string,format,arg1, arg2, ...);
This is my latest version of the "sprintf" standard library
routine. This time, folks, it REALLY IS standard. I've
tried to make it EXACTLY the same as the version presented
in Kernighan & Ritchie: right-justification of fields is
now the default instead of left-justification (you can GET
left-justification by using a dash in the conversion, as
specified in the book); the "%s" conversion can take a precision
now as well as a field width; the "e" and "f" conversions, for
floating point numbers, are supported in a special version of
"sprintf" given in source form in the FLOAT.C file. If you do
a lot of number crunching and wish t